Skip to content

fix(angular-query): call withDevtools function within injection conte… #9236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

michaelbe812
Copy link
Contributor

…xt to not throw

Bug description

Following this example:

@Injectable({ providedIn: 'root' })
class DevtoolsOptionsManager {
  loadDevtools = toSignal(
    fromEvent<KeyboardEvent>(document, 'keydown').pipe(
      map(
        (event): boolean =>
          event.metaKey && event.ctrlKey && event.shiftKey && event.key === 'D',
      ),
      scan((acc, curr) => acc || curr, false),
    ),
    {
      initialValue: false,
    },
  )
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(),
    provideTanStackQuery(
      new QueryClient(),
      withDevtools(() => ({
        initialIsOpen: true,
        loadDevtools: inject(DevtoolsOptionsManager).loadDevtools(),
      })),
    ),
  ],
}

will throw a runtime error that inject must be called from within an injection context.

CleanShot 2025 06 03 - Google Chrome-TanStack Query devtools panel example-000777@2x

CleanShot 2025 06 03 - Google Chrome-TanStack Query devtools panel example-000779@2x

Copy link

nx-cloud bot commented Jun 3, 2025

View your CI Pipeline Execution ↗ for commit e0cb4c8.

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 2m 20s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 11s View ↗

☁️ Nx Cloud last updated this comment at 2025-06-04 05:45:50 UTC

Copy link

pkg-pr-new bot commented Jun 3, 2025

More templates

@tanstack/angular-query-devtools-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-devtools-experimental@9236

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@9236

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@9236

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@9236

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@9236

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@9236

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@9236

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@9236

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@9236

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@9236

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@9236

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@9236

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@9236

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@9236

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@9236

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@9236

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@9236

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@9236

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@9236

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@9236

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@9236

commit: e0cb4c8

Copy link

codecov bot commented Jun 3, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 85.98%. Comparing base (058bfc9) to head (e0cb4c8).
Report is 9 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #9236       +/-   ##
===========================================
+ Coverage   45.33%   85.98%   +40.64%     
===========================================
  Files         207       16      -191     
  Lines        8271      321     -7950     
  Branches     1860       75     -1785     
===========================================
- Hits         3750      276     -3474     
+ Misses       4080       40     -4040     
+ Partials      441        5      -436     
Components Coverage Δ
@tanstack/angular-query-devtools-experimental ∅ <ø> (∅)
@tanstack/angular-query-experimental 85.09% <100.00%> (+0.09%) ⬆️
@tanstack/eslint-plugin-query ∅ <ø> (∅)
@tanstack/query-async-storage-persister ∅ <ø> (∅)
@tanstack/query-broadcast-client-experimental ∅ <ø> (∅)
@tanstack/query-codemods ∅ <ø> (∅)
@tanstack/query-core ∅ <ø> (∅)
@tanstack/query-devtools ∅ <ø> (∅)
@tanstack/query-persist-client-core ∅ <ø> (∅)
@tanstack/query-sync-storage-persister ∅ <ø> (∅)
@tanstack/query-test-utils ∅ <ø> (∅)
@tanstack/react-query ∅ <ø> (∅)
@tanstack/react-query-devtools ∅ <ø> (∅)
@tanstack/react-query-next-experimental ∅ <ø> (∅)
@tanstack/react-query-persist-client ∅ <ø> (∅)
@tanstack/solid-query ∅ <ø> (∅)
@tanstack/solid-query-devtools ∅ <ø> (∅)
@tanstack/solid-query-persist-client ∅ <ø> (∅)
@tanstack/svelte-query ∅ <ø> (∅)
@tanstack/svelte-query-devtools ∅ <ø> (∅)
@tanstack/svelte-query-persist-client ∅ <ø> (∅)
@tanstack/vue-query ∅ <ø> (∅)
@tanstack/vue-query-devtools ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@michaelbe812
Copy link
Contributor Author

Just have to think about how to write a test case for it - help welcome :)

@michaelbe812 michaelbe812 force-pushed the fix/withdevtools-throws branch from b052807 to e0cb4c8 Compare June 4, 2025 05:42
@arnoud-dv
Copy link
Collaborator

I don't think a computation function should use inject, which is why I removed runInInjectionContext, forgetting that it breaks the use case and my own example code.

There's good reasons Angular doesn't run computed and such in the injection context. inject should run once something (a component, service, provider etc.) is initialized and not getting the injectable continuously during the "something" its lifetime. But I do want to support using a value from an injectable. I got a devtools branch locally which allows injectables to be used as such:

export const appConfig: ApplicationConfig = {
  providers: [
    provideTanStackQuery(
      new QueryClient(),
      withDevtools(
        (devToolsOptionsManager: DevtoolsOptionsManager) => ({
          loadDevtools: devToolsOptionsManager.loadDevtools(),
        }),
        {
          // `deps` can be used to pass one or more injectables as parameters to the `withDevtools` callback.
          deps: [DevtoolsOptionsManager],
        },
      ),
    ),
  ],
}

It's similar to the Angular deps mechanism in providers. Like with Angular deps the parameter does need explicit typing. What do you think about this API?

It is possible to add type inference to the Angular adapter's types btw, but because of TypeScript limitations it would need a separate overload per number of deps array items. Which is kind of clunky and why I choose not to add that for now.

The branch also adds conditional exports which greatly improves tree shaking and other devtools improvements. Haven't touched it in a month, I'll review it a bit and see if I can open a PR.

@michaelbe812
Copy link
Contributor Author

I don't think a computation function should use inject, which is why I removed runInInjectionContext, forgetting that it breaks the use case and my own example code.

There's good reasons Angular doesn't run computed and such in the injection context. inject should run once something (a component, service, provider etc.) is initialized and not getting the injectable continuously during the "something" its lifetime. But I do want to support using a value from an injectable. I got a devtools branch locally which allows injectables to be used as such:

export const appConfig: ApplicationConfig = {
  providers: [
    provideTanStackQuery(
      new QueryClient(),
      withDevtools(
        (devToolsOptionsManager: DevtoolsOptionsManager) => ({
          loadDevtools: devToolsOptionsManager.loadDevtools(),
        }),
        {
          // `deps` can be used to pass one or more injectables as parameters to the `withDevtools` callback.
          deps: [DevtoolsOptionsManager],
        },
      ),
    ),
  ],
}

It's similar to the Angular deps mechanism in providers. Like with Angular deps the parameter does need explicit typing. What do you think about this API?

It is possible to add type inference to the Angular adapter's types btw, but because of TypeScript limitations it would need a separate overload per number of deps array items. Which is kind of clunky and why I choose not to add that for now.

The branch also adds conditional exports which greatly improves tree shaking and other devtools improvements. Haven't touched it in a month, I'll review it a bit and see if I can open a PR.

Hey I generally agree with everything especially the part regarding computed.

For me personally this API looks fine. I do not see any major advantages or disadvantages of having another syntax. It does the job and it should be quite understandable.

@michaelbe812 michaelbe812 deleted the fix/withdevtools-throws branch June 5, 2025 13:45
@arnoud-dv
Copy link
Collaborator

Cool thanks, gives me confidence to move forward with this. API design, thinking of many use cases and avoiding future breaking changes is hard 😅

@michaelbe812
Copy link
Contributor Author

Cool thanks, gives me confidence to move forward with this. API design, thinking of many use cases and avoiding future breaking changes is hard 😅

Agree - This is a complete different discipline :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants